import { ethers } from 'ethers';
import { useSiweMessage } from './useSiweMessage';
import { ref, readonly } from 'vue';

interface WalletOptions {
  autoConnect?: boolean;
  provider: ethers.providers.JsonRpcProvider;
}
export function useWallet(options: WalletOptions) {
  const { provider } = options;
  if (!provider) {
    throw new Error('options.provider is required');
  }

  const signer = provider.getSigner();
  const address = ref('');
  const isConnecting = ref(false);
  const isConnected = ref(false);
  const isSigningMessage = ref(false);

  async function connect() {
    isConnecting.value = true;
    await provider
      .send('eth_requestAccounts', [])
      .catch(() => console.log('user rejected request'));

    isConnecting.value = false;
    address.value = await signer.getAddress();
    isConnected.value = true;
  }

  // ====== disconnect ======
  function useDisconnect() {
    const isError = ref(false);
    const isLoading = ref(false);
    const isSuccess = ref(false);
    const error = ref();
    async function disconnect() {
      try {
        isLoading.value = true;
        await provider.send('eth_requestAccounts', []);
        isSuccess.value = true;
      } catch (err) {
        isError.value = true;
        error.value = err;
        console.log('user rejected disconnect');
      } finally {
        isLoading.value = false;
      }

      isConnected.value = false;
    }

    return {
      disconnect,
      error: readonly(error),
      isError: readonly(isError),
      isLoading: readonly(isLoading),
      isSuccess: readonly(isSuccess),
    };
  }

  async function getBalance(address) {
    const balance = await provider.getBalance(address);
    return balance;
  }

  // ====== sign message ======
  function useSignMessage() {
    const data = ref('');
    const isError = ref(false);
    const isLoading = ref(false);
    const isSuccess = ref(false);
    const error = ref();

    async function signMessage(args = { message: 'Sign in to the app.', nonce: '' }) {
      try {
        isLoading.value = true;
        const { message: msg } = useSiweMessage({
          address: await signer.getAddress(),
          statement: args.message,
          nonce: args.nonce,
        });

        isSuccess.value = true;
        data.value = await signer.signMessage(msg.value);
        isSigningMessage.value = false;
      } catch (err) {
        isError.value = true;
        error.value = err;
        console.log('user rejected sign message');
      } finally {
        isLoading.value = false;
      }
      return data.value;
    }

    return {
      signMessage,
      data: readonly(data),
      error: readonly(error),
      isError: readonly(isError),
      isLoading: readonly(isLoading),
      isSuccess: readonly(isSuccess),
    };
  }

  return {
    address: readonly(address),
    isConnecting: readonly(isConnecting),
    isConnected: readonly(isConnected),
    useSignMessage,
    useDisconnect,
    connect,
    getBalance,
  };
}
